package com.weir.oauth2.server.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

/**
 * 配置授权中心信息
 * @author weir
 *
 * 2018年11月28日 下午2:29:51
 */
@Configuration
@EnableAuthorizationServer // 开启认证授权中心
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
	// accessToken有效期
	private static final int ACCESSTOKENVALIDITYSECONDS = 7200; // 两小时
	//刷新令牌
	private static final int REFRESHTOKENVALIDITYSECONDS = 7200; // 两小时

	// 添加商户信息
	public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
		//申请appID和key、回调地址、token有效期
		// withClient appid
		clients.inMemory()//内存模式
		       .withClient("weir")//appID
		       .secret(passwordEncoder().encode("123456"))//key
		       .redirectUris("https://www.baidu.com")//回调地址
			   .authorizedGrantTypes("password","client_credentials","refresh_token")//（授权类型）密码模式
			   .scopes("all")//授权范围
			   .accessTokenValiditySeconds(ACCESSTOKENVALIDITYSECONDS)//token有效期
			   .refreshTokenValiditySeconds(REFRESHTOKENVALIDITYSECONDS);//刷新令牌时间
	}

	// 设置token类型，可以通过get或post方式获取到
	public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
		endpoints.authenticationManager(authenticationManager())
				.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);
		endpoints.authenticationManager(authenticationManager());
		endpoints.userDetailsService(userDetailsService());
	}

	@Override
	public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
		// 允许表单认证
		oauthServer.allowFormAuthenticationForClients();
		// 允许check_token访问
		oauthServer.checkTokenAccess("permitAll()");
	}

	@Bean
	AuthenticationManager authenticationManager() {
		AuthenticationManager authenticationManager = new AuthenticationManager() {

			public Authentication authenticate(Authentication authentication)
					throws AuthenticationException {
				return daoAuhthenticationProvider().authenticate(authentication);
			}
		};
		return authenticationManager;
	}

	@Bean
	public AuthenticationProvider daoAuhthenticationProvider() {
		DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
		daoAuthenticationProvider.setUserDetailsService(userDetailsService());
		daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
		daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
		return daoAuthenticationProvider;
	}

	// 设置添加用户信息,正常应该从数据库中读取
	@Bean
	UserDetailsService userDetailsService() {
		InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager();
		userDetailsService.createUser(User.withUsername("weir1")
				.password(passwordEncoder().encode("123456")).authorities("ROLE_USER").build());
		userDetailsService.createUser(User.withUsername("weir")
				.password(passwordEncoder().encode("1234567")).authorities("ROLE_USER").build());
		return userDetailsService;
	}

	@Bean
	PasswordEncoder passwordEncoder() {
		// 加密方式
		PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
		return passwordEncoder;
	}
}